package com.gec.anan.driver.service.impl;


import cn.binarywang.wx.miniapp.api.WxMaService;
import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.gec.anan.common.constant.SystemConstant;
import com.gec.anan.common.execption.AnanException;
import com.gec.anan.common.result.ResultCodeEnum;
import com.gec.anan.driver.config.TencentCloudProperties;
import com.gec.anan.driver.mapper.*;
import com.gec.anan.driver.service.CosService;
import com.gec.anan.driver.service.DriverInfoService;
import com.gec.anan.model.entity.driver.*;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.gec.anan.model.form.driver.DriverFaceModelForm;
import com.gec.anan.model.form.driver.UpdateDriverAuthInfoForm;
import com.gec.anan.model.form.map.UpdateDriverLocationForm;
import com.gec.anan.model.vo.driver.DriverAuthInfoVo;
import com.gec.anan.model.vo.driver.DriverInfoVo;
import com.gec.anan.model.vo.driver.DriverLoginVo;
import com.tencentcloudapi.common.AbstractModel;
import com.tencentcloudapi.common.Credential;
import com.tencentcloudapi.common.exception.TencentCloudSDKException;
import com.tencentcloudapi.common.profile.ClientProfile;
import com.tencentcloudapi.common.profile.HttpProfile;
import com.tencentcloudapi.iai.v20200303.IaiClient;
import com.tencentcloudapi.iai.v20200303.models.*;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.error.WxErrorException;
import org.checkerframework.checker.units.qual.A;
import org.joda.time.DateTime;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.math.BigDecimal;
import java.util.Date;

@Slf4j
@Service
@SuppressWarnings({"unchecked", "rawtypes"})
public class DriverInfoServiceImpl extends ServiceImpl<DriverInfoMapper, DriverInfo> implements DriverInfoService {

    @Autowired
    private TencentCloudProperties tencentCloudProperties;
    @Autowired
    private WxMaService service;

    @Autowired
    private DriverInfoMapper driverInfoMapper;

    @Autowired
    private DriverSetMapper driverSetMapper;

    @Autowired
    private DriverAccountMapper driverAccountMapper;

    @Autowired
    private DriverLoginLogMapper driverLoginLogMapper;

    @Autowired
    private DriverFaceRecognitionMapper driverFaceRecognitionMapper;
    @Autowired
    private CosService cosService;

    //司机登陆
    @Override
    public Long login(String code) {
//        try {
//            WxMaJscode2SessionResult sessionInfo = service.getUserService().getSessionInfo(code);
//            String openid = sessionInfo.getOpenid();
//
//            LambdaQueryWrapper<DriverInfo> queryWrapper = new LambdaQueryWrapper<>();
//            queryWrapper.eq(DriverInfo::getWxOpenId, openid );
//            DriverInfo driverInfo = driverInfoMapper.selectOne(queryWrapper);
//
//            if(driverInfo==null){
//                driverInfo  = new DriverInfo();
//                driverInfo.setWxOpenId(openid);
//                driverInfoMapper.insert(driverInfo);
//
//                DriverSet driverSet = new DriverSet();
//                driverSet.setDriverId(driverInfo.getId());
//                driverSetMapper.insert(driverSet);
//                DriverAccount driverAccount = new DriverAccount();
//                driverAccount.setDriverId(driverInfo.getId());
//                driverAccountMapper.insert(driverAccount);
//            }
//            DriverLoginLog driverLoginLog = new DriverLoginLog();
//            driverLoginLog.setDriverId(driverInfo.getId());
//            return driverInfo.getId();
//        } catch (WxErrorException e) {
//            throw new RuntimeException(e);
//        }


        //1.获取唯一的openid
        WxMaJscode2SessionResult sessionInfo = null;
        String openid = null;
        try {
            sessionInfo = service.getUserService().getSessionInfo(code);
            openid = sessionInfo.getOpenid();
        } catch (WxErrorException e) {
            throw new RuntimeException(e);
        }

        //2.查询数据库
        LambdaQueryWrapper<DriverInfo> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(DriverInfo::getWxOpenId, openid);
        DriverInfo driverInfo = driverInfoMapper.selectOne(queryWrapper);

        //3.第一次登陆则注册
        if (driverInfo == null) {
            driverInfo = new DriverInfo();
            driverInfo.setWxOpenId(openid);
            driverInfo.setNickname(String.valueOf(System.currentTimeMillis()));
            driverInfo.setAvatarUrl("https://oss.aliyuncs.com/aliyun_id_photo_bucket/default_handsome.jpg");
            driverInfoMapper.insert(driverInfo);

            //初始化司机接单配置
            DriverSet driverSet = new DriverSet();
            driverSet.setDriverId(driverInfo.getId());
            //是否自动接单，默认为自动接单
            driverSet.setIsAutoAccept(0);
            driverSet.setOrderDistance(new BigDecimal(0));//订单距离无限制
            driverSet.setOrderDistance(new BigDecimal(SystemConstant.ACCEPT_DISTANCE));
            driverSetMapper.insert(driverSet);

            //初始化司机账户信息
            DriverAccount driverAccount = new DriverAccount();
            driverAccount.setDriverId(driverInfo.getId());
            driverAccountMapper.insert(driverAccount);
        }

        //写入redis中


        //4.记录日志
        DriverLoginLog driverLoginLog = new DriverLoginLog();
        driverLoginLog.setDriverId(driverInfo.getId());
        driverLoginLog.setMsg("司机id：" + driverInfo.getId() + "使用小程序登陆");
        driverLoginLogMapper.insert(driverLoginLog);
        //5.无论是否第一次登陆，都要返回driverId
        return driverInfo.getId();
    }

    //获取登陆信息
    @Override
    public DriverLoginVo getDriverLoginInfo(Long driverId) {
//        DriverInfo driverInfo = driverInfoMapper.selectById(driverId);
//        DriverLoginVo driverLoginVo = new DriverLoginVo();
//        BeanUtils.copyProperties(driverInfo, driverLoginVo);
//        String faceModelId = driverInfo.getFaceModelId();
//        boolean b = StringUtils.hasText(faceModelId);
//        driverLoginVo.setIsArchiveFace(b);
//        return driverLoginVo;

        //1.从数据库中查询driverInfo对象
        DriverInfo driverInfo = driverInfoMapper.selectById(driverId);
        if (driverInfo == null) {
            throw new AnanException(ResultCodeEnum.DATA_ERROR);
        }
        //2.copy一份到vo用于前后端数据传输
        DriverLoginVo driverLoginVo = new DriverLoginVo();
        BeanUtils.copyProperties(driverInfo, driverLoginVo);
        //缺少的信息补上
        boolean flag = StringUtils.hasText(driverInfo.getFaceModelId());
        driverLoginVo.setIsArchiveFace(flag);
        //3.返回vo对象
        return driverLoginVo;
    }

    //获取认证信息
    @Override
    public DriverAuthInfoVo getDriverAuthInfo(Long driverId) {
        //1.根据driverId从数据库查询数据
        DriverInfo driverInfo = driverInfoMapper.selectById(driverId);
        if (driverInfo == null) {
            throw new AnanException(210, "没有账号数据");
        }
        DriverAuthInfoVo driverAuthInfoVo = new DriverAuthInfoVo();
        BeanUtils.copyProperties(driverInfo, driverAuthInfoVo);
        driverAuthInfoVo.setIdcardFrontUrl(cosService.getImageUrl(driverAuthInfoVo.getIdcardFrontUrl()));
        driverAuthInfoVo.setIdcardBackUrl(cosService.getImageUrl(driverAuthInfoVo.getIdcardBackUrl()));
        driverAuthInfoVo.setIdcardHandShowUrl(cosService.getImageUrl(driverAuthInfoVo.getIdcardHandUrl()));
        driverAuthInfoVo.setDriverLicenseFrontUrl(cosService.getImageUrl(driverAuthInfoVo.getDriverLicenseFrontUrl()));
        driverAuthInfoVo.setDriverLicenseBackUrl(cosService.getImageUrl(driverAuthInfoVo.getDriverLicenseBackUrl()));
        driverAuthInfoVo.setDriverLicenseHandUrl(cosService.getImageUrl(driverAuthInfoVo.getDriverLicenseHandUrl()));
        return driverAuthInfoVo;
    }


    //司机更新认证信息
    @Transactional(rollbackFor = Exception.class)
    @Override
    public Boolean updateDriverAuthInfo(UpdateDriverAuthInfoForm updateDriverAuthInfoForm) {
        DriverInfo driverInfo = new DriverInfo();
        driverInfo.setId(updateDriverAuthInfoForm.getDriverId());
        BeanUtils.copyProperties(updateDriverAuthInfoForm, driverInfo);
        //修改司机的验证状态
        driverInfo.setAuthStatus(2);
        return this.updateById(driverInfo);
    }

    //司机人脸模型
    @Override
    public Boolean creatDriverFaceModel(DriverFaceModelForm driverFaceModelForm) {
        //1.根据司机的id获取driverInfo
        DriverInfo driverInfo = driverInfoMapper.selectById(driverFaceModelForm.getDriverId());

        //2.腾讯云人脸识别的官方代码
        try {
            // 实例化一个认证对象，入参需要传入腾讯云账户 SecretId 和 SecretKey，此处还需注意密钥对的保密
            // 代码泄露可能会导致 SecretId 和 SecretKey 泄露，并威胁账号下所有资源的安全性。以下代码示例仅供参考，建议采用更安全的方式来使用密钥，请参见：https://cloud.tencent.com/document/product/1278/85305
            // 密钥可前往官网控制台 https://console.cloud.tencent.com/cam/capi 进行获取
            Credential cred = new Credential(tencentCloudProperties.getSecretId(), tencentCloudProperties.getSecretKey());
            // 实例化一个http选项，可选的，没有特殊需求可以跳过
            HttpProfile httpProfile = new HttpProfile();
            httpProfile.setEndpoint("iai.tencentcloudapi.com");
            // 实例化一个client选项，可选的，没有特殊需求可以跳过
            ClientProfile clientProfile = new ClientProfile();
            clientProfile.setHttpProfile(httpProfile);
            // 实例化要请求产品的client对象,clientProfile是可选的
            IaiClient client = new IaiClient(cred, tencentCloudProperties.getRegion(), clientProfile);
            // 实例化一个请求对象,每个接口都会对应一个request对象
            CreatePersonRequest req = new CreatePersonRequest();
            req.setGroupId(tencentCloudProperties.getPersionGroupId());
            //基本信息
            req.setPersonId(String.valueOf(driverInfo.getId()));
            System.out.println("建立人脸模型时候录入的driverId:" + driverInfo.getId());
            req.setGender(Long.parseLong(driverInfo.getGender()));
            req.setQualityControl(4L);
            req.setUniquePersonControl(4L);
            req.setPersonName(driverInfo.getName());
            req.setImage(driverFaceModelForm.getImageBase64());

            // 返回的resp是一个CreatePersonResponse的实例，与请求对象对应
            CreatePersonResponse resp = client.CreatePerson(req);
            // 输出json格式的字符串回包
            System.out.println(AbstractModel.toJsonString(resp));
            //3.设置人脸faceId，更新信息
            String faceId = resp.getFaceId();
            log.info("人脸id:【】", faceId);
            System.out.println("获得到的人脸id:" + faceId);
            if (StringUtils.hasText(faceId)) {

                driverInfo.setFaceModelId(faceId);
                driverInfoMapper.updateById(driverInfo);
            }
        } catch (TencentCloudSDKException e) {
            System.out.println(e.toString());
            e.printStackTrace();
        }
        return true;
    }

    @Override
    public DriverSet getDriverSet(Long driverId) {
        //根据driverId查询司机的个人设置
        LambdaQueryWrapper<DriverSet> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(DriverSet::getDriverId, driverId);
        DriverSet driverSet = driverSetMapper.selectOne(queryWrapper);
        return driverSet;
    }


    @Override
    public Boolean verifyDriverFace(DriverFaceModelForm driverFaceModelForm) {
        //进行人脸识别
/**
 * 人脸验证
 * 文档地址：
 * https://cloud.tencent.com/document/api/867/44983
 * https://console.cloud.tencent.com/api/explorer?Product=iai&Version=2020-03-03&Action=VerifyFace
 *
 * @param driverFaceModelForm
 * @return
 */
        //1.先普通的照片识别
        try {
            // 实例化一个认证对象，入参需要传入腾讯云账户 SecretId 和 SecretKey，此处还需注意密钥对的保密
            // 代码泄露可能会导致 SecretId 和 SecretKey 泄露，并威胁账号下所有资源的安全性。以下代码示例仅供参考，建议采用更安全的方式来使用密钥，请参见：https://cloud.tencent.com/document/product/1278/85305
            // 密钥可前往官网控制台 https://console.cloud.tencent.com/cam/capi 进行获取
            Credential cred = new Credential(tencentCloudProperties.getSecretId(), tencentCloudProperties.getSecretKey());
            // 实例化一个http选项，可选的，没有特殊需求可以跳过
            HttpProfile httpProfile = new HttpProfile();
            httpProfile.setEndpoint("iai.tencentcloudapi.com");
            // 实例化一个client选项，可选的，没有特殊需求可以跳过
            ClientProfile clientProfile = new ClientProfile();
            clientProfile.setHttpProfile(httpProfile);
            // 实例化要请求产品的client对象,clientProfile是可选的
            IaiClient client = new IaiClient(cred, tencentCloudProperties.getRegion(), clientProfile);
            // 实例化一个请求对象,每个接口都会对应一个request对象
            VerifyFaceRequest req = new VerifyFaceRequest();
            req.setImage(driverFaceModelForm.getImageBase64());
            req.setPersonId(String.valueOf(driverFaceModelForm.getDriverId()));
            System.out.println("driverId:" + driverFaceModelForm.getDriverId());
            // 返回的resp是一个VerifyFaceResponse的实例，与请求对象对应
            VerifyFaceResponse resp = client.VerifyFace(req);
            // 输出json格式的字符串回包
            System.out.println(AbstractModel.toJsonString(resp));

            Boolean isMatch = resp.getIsMatch();
            System.out.println(isMatch);
            if (isMatch) {
                System.out.println("成功进入静态活体识别");
                //2.照片识别成功后进行静态活体识别
                if (this.detectLiveFace(driverFaceModelForm.getImageBase64())) {
                    DriverFaceRecognition driverFaceRecognition = new DriverFaceRecognition();
                    driverFaceRecognition.setDriverId(driverFaceModelForm.getDriverId());
                    driverFaceRecognition.setFaceDate(new Date());
                    System.out.println("静态活体人脸识别成功");
                    //3.存入数据库中
                    driverFaceRecognitionMapper.insert(driverFaceRecognition);
                }
            }

        } catch (TencentCloudSDKException e) {
            System.out.println(e.toString());
            e.printStackTrace();
        }

        return null;
    }

    /**
     * 人脸静态活体检测
     * 文档地址：
     * https://cloud.tencent.com/document/api/867/48501
     * https://console.cloud.tencent.com/api/explorer?Product=iai&Version=2020-03-03&Action=DetectLiveFace
     *
     * @param imageBase64
     * @return
     */
    private boolean detectLiveFace(String imageBase64) {
        try {
            // 实例化一个认证对象，入参需要传入腾讯云账户 SecretId 和 SecretKey，此处还需注意密钥对的保密
            // 代码泄露可能会导致 SecretId 和 SecretKey 泄露，并威胁账号下所有资源的安全性。以下代码示例仅供参考，建议采用更安全的方式来使用密钥，请参见：https://cloud.tencent.com/document/product/1278/85305
            // 密钥可前往官网控制台 https://console.cloud.tencent.com/cam/capi 进行获取
            Credential cred = new Credential(tencentCloudProperties.getSecretId(), tencentCloudProperties.getSecretKey());
            // 实例化一个http选项，可选的，没有特殊需求可以跳过
            HttpProfile httpProfile = new HttpProfile();
            httpProfile.setEndpoint("iai.tencentcloudapi.com");
            // 实例化一个client选项，可选的，没有特殊需求可以跳过
            ClientProfile clientProfile = new ClientProfile();
            clientProfile.setHttpProfile(httpProfile);
            // 实例化要请求产品的client对象,clientProfile是可选的
            IaiClient client = new IaiClient(cred, tencentCloudProperties.getRegion(), clientProfile);
            // 实例化一个请求对象,每个接口都会对应一个request对象
            DetectLiveFaceRequest req = new DetectLiveFaceRequest();
            req.setImage(imageBase64);
            // 返回的resp是一个DetectLiveFaceResponse的实例，与请求对象对应
            DetectLiveFaceResponse resp = client.DetectLiveFace(req);
            // 输出json格式的字符串回包
            System.out.println(DetectLiveFaceResponse.toJsonString(resp));
            if (resp.getIsLiveness()) {
                return true;
            }
        } catch (TencentCloudSDKException e) {
            System.out.println(e.toString());
        }
        return false;
    }

    //查询司机当日是否进行人脸识别
    @Override
    public Boolean isFaceRecognition(Long driverId) {
        LambdaQueryWrapper<DriverFaceRecognition> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(DriverFaceRecognition::getDriverId, driverId);
        Long count = driverFaceRecognitionMapper.selectCount(queryWrapper);
        return count != 0;
    }

    //更改司机的接单状态
    @Transactional
    @Override
    public Boolean updateServiceStatus(Long driverId, Integer status) {
        LambdaQueryWrapper<DriverSet> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(DriverSet::getDriverId, driverId);
        DriverSet driverSet = new DriverSet();
        driverSet.setServiceStatus(status);
        driverSetMapper.update(driverSet, queryWrapper);
        return true;
    }

    //获取司机的基本信息(头像、姓名、驾龄)
    @Override
    public DriverInfoVo getDriverInfo(Long driverId) {
        DriverInfo driverInfo = this.getById(driverId);
        DriverInfoVo driverInfoVo = new DriverInfoVo();
        BeanUtils.copyProperties(driverInfo, driverInfoVo);
        //驾龄
        Integer driverLicenseAge = new DateTime().getYear() - new DateTime(driverInfo.getDriverLicenseIssueDate()).getYear() + 1;
        driverInfoVo.setDriverLicenseAge(driverLicenseAge);
        return driverInfoVo;
    }

    //获取司机的openid
    @Override
    public String getDriverOpenId(Long driverId) {
        LambdaQueryWrapper<DriverInfo> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(DriverInfo::getId, driverId);
        queryWrapper.select(DriverInfo::getWxOpenId);
        DriverInfo driverInfo = driverInfoMapper.selectOne(queryWrapper);
        return driverInfo.getWxOpenId();
    }
}